package com.fy.filter;

import cn.hutool.json.JSONUtil;
import com.fy.common.exception.JWTParseException;
import com.fy.common.util.JwtUtils;
import com.fy.common.util.RsaUtils;
import com.fy.common.vo.ResultVo;
import com.fy.module.user.entity.User;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.PublicKey;
import java.util.List;

public class JwtVerifyFilter extends BasicAuthenticationFilter {

    public JwtVerifyFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        //自定义实现
        //放行登录
        if("/user/login".equals(request.getRequestURI())){
            chain.doFilter(request, response);
            return;
        }
        //放行options
        if("OPTIONS".equalsIgnoreCase(request.getMethod())){
            chain.doFilter(request, response);
            return;
        }
        //1、从请求头获取 jwt 令牌
        String token = request.getHeader("token");
        if(StringUtils.isEmpty(token)) {
            //响应客户端
            responseClient(new ResultVo(false, "令牌不能为空"), response, HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }
        //2、校验令牌是否合法
        PublicKey publicKey = null;
        try {
//            publicKey = RsaUtils.getPublicKey(ResourceUtils.getFile("classpath:pub_rsa").getPath());
            publicKey = RsaUtils.getPublicKey(RsaUtils.readBytes3(new ClassPathResource("pub_rsa").getInputStream()));
            User user = (User) JwtUtils.getInfoFromToken(token, publicKey, User.class);

            //获取用户的角色和权限列表
            String rolePermisson = user.getRolePermisson();
            List<GrantedAuthority> authoritites = AuthorityUtils.commaSeparatedStringToAuthorityList(rolePermisson);

            //3:将用户信息存到 securityContext
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken
                    = new UsernamePasswordAuthenticationToken(user, null, authoritites);
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);

            //放行
            chain.doFilter(request, response);


        } catch (Exception e) {
            if(e instanceof JWTParseException){
                //非法令牌
                responseClient(new ResultVo(false, e.getMessage()), response, HttpServletResponse.SC_UNAUTHORIZED);
                return;
            }
            responseClient(new ResultVo(false, e.getMessage()), response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            //非法令牌

        }

    }

    private void responseClient(ResultVo resultVo, HttpServletResponse response, int status){
        response.setContentType("application/json;charset=utf-8");
        response.setStatus(status);
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        writer.write(JSONUtil.toJsonStr(resultVo));
        if(writer!=null) writer.close();
    }
}
